package console

import (
	"context"
	"sync"

	"code.byted.org/bytertc/whiteboard_server/biz/api"
	"code.byted.org/bytertc/whiteboard_server/biz/dal"
	"code.byted.org/bytertc/whiteboard_server/biz/dal/spec"
	"code.byted.org/gopkg/logs/v2/log"
)

type Config interface {
	GetInfo(ctx context.Context, unique spec.ConsoleBaseUnique) (*api.GetConsoleInfoResponse, error)
	SetInfo(ctx context.Context, unique spec.ConsoleItemUnique) error
	Switch(ctx context.Context, unique spec.ConsoleSwitchUnique) error
	DeleteItem(ctx context.Context, unique spec.ConsoleBaseUnique) error
}

var once sync.Once
var mCfg *config

const (
	Type_Transcode = iota + 1
	Type_Record
)
const Enabled = 1

func NewConfig(repo dal.Repo) Config {
	if mCfg == nil {
		once.Do(func() {
			mCfg = &config{
				repo: repo,
			}
		},
		)
	}
	return mCfg
}

type config struct {
	repo dal.Repo
}

func (c *config) GetInfo(ctx context.Context, unique spec.ConsoleBaseUnique) (*api.GetConsoleInfoResponse, error) {
	switchInfos, err := c.repo.GetSwitchInfos(ctx, unique)
	if err != nil {
		log.V1.CtxError(ctx, "console GetSwitchInfos err:%+v,appId:%s", err, unique.GetAppId())
		return nil, err
	}
	ret := &api.GetConsoleInfoResponse{
		Transcode: api.ItemInfo{},
		Record:    api.ItemInfo{},
	}
	for _, Info := range switchInfos {
		if Info.Category != dal.Category_Switch_Record && Info.Category != dal.Category_Switch_Transcode {
			log.V1.CtxError(ctx, "SwitchInfo include invalid category, appId:%s", unique.GetAppId())
			continue
		}
		if Info.Status == dal.Switch_OFF {
			continue
		}
		configs, err := c.repo.GetConfigs(ctx, unique.GetAppId(), Info.Category)
		if err != nil {
			log.V1.CtxError(ctx, "console GetConfigs err:%+v,appId:%s", err, unique.GetAppId())
			return nil, err
		}
		if Info.Category == dal.Category_Switch_Transcode {
			ret.Transcode.OpenStatus = Info.Status
			ret.Transcode.ItemDetails = make([]api.ItemDetail, 0)
			for _, config := range configs {
				detail := api.ItemDetail{
					SpaceType: config.SpaceType,
					Space:     config.Space,
					Category:  config.Category,
				}
				ret.Transcode.ItemDetails = append(ret.Transcode.ItemDetails, detail)
			}

		}
		if Info.Category == dal.Category_Switch_Record {
			ret.Record.OpenStatus = Info.Status
			ret.Record.ItemDetails = make([]api.ItemDetail, 0)
			for _, config := range configs {
				detail := api.ItemDetail{
					SpaceType: config.SpaceType,
					Space:     config.Space,
					Category:  config.Category,
				}
				ret.Record.ItemDetails = append(ret.Record.ItemDetails, detail)
			}

		}

	}
	return ret, nil
}

func (c *config) SetInfo(ctx context.Context, unique spec.ConsoleItemUnique) error {
	configs, err := c.repo.GetConfig(ctx, unique, true)
	if err != nil {
		log.V1.CtxError(ctx, "console GetConfig err:%+v,unique:%+v", err, unique)
		return err
	}
	if len(configs) > 0 {
		err = c.repo.UpdateConfig(ctx, unique)
		if err != nil {
			log.V1.CtxError(ctx, "console UpdateConfig err:%+v,unique:%+v", err, unique)
			return err
		}
	} else {
		err = c.repo.SetConfig(ctx, unique)
		if err != nil {
			log.V1.CtxError(ctx, "console SetConfig err:%+v,unique:%+v", err, unique)
			return err
		}
	}
	return nil
}

func (c *config) DeleteItem(ctx context.Context, unique spec.ConsoleBaseUnique) error {
	err := c.repo.DeleteConfig(ctx, unique)
	if err != nil {
		log.V1.CtxError(ctx, "console DeleteConfig err:%+v,unique:%+v", err, unique)
		return err
	}
	return nil

}

func (c *config) Switch(ctx context.Context, unique spec.ConsoleSwitchUnique) error {

	infos, err := c.repo.GetSwitchInfo(ctx, unique)
	if err != nil {
		log.V1.CtxError(ctx, "console GetSwitchInfo err:%+v,unique:%+v", err, unique)
		return err
	}
	if len(infos) > 0 {
		err = c.repo.UpdateSwitchInfo(ctx, unique)
		if err != nil {
			log.V1.CtxError(ctx, "console UpdateSwitchInfo err:%+v,unique:%+v", err, unique)
			return err
		}
	} else {
		err = c.repo.CreateSwitchInfo(ctx, unique)
		if err != nil {
			log.V1.CtxError(ctx, "console CreateSwitchInfo err:%+v,unique:%+v", err, unique)
			return err
		}
	}
	return nil
}
